package com.oristartech.netty.server.starter;

import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 ** Netty客户端连接池
 *
 * @author: chenfenghai
 * @version: 1.0
 * @date: 2020-03-10 10:34
 * @blame Team
 */
@Slf4j
@Component
public class NettyClientPool {

    /**
     ** Netty客户端Map
     */
    private static ConcurrentMap<String, NettyClientWrapper> nettyClientMap = new ConcurrentHashMap<>();

    /**
     ** 缓存客户端
     *
     * @param tenantId 租户ID
     * @param cinemaCode 影院编码
     * @param channel 客户端通道
     */
    public void putClient(String tenantId, String cinemaCode, Channel channel){
        NettyClientWrapper nettyClient = new NettyClientWrapper(tenantId, cinemaCode, channel);
        String uniqueKey = buildClientUniqueKey(tenantId, cinemaCode);
        nettyClientMap.put(uniqueKey, nettyClient);
    }

    /**
     ** 根据租户ID、影院编码获取客户端
     *
     * @param tenantId 租户ID
     * @param cinemaCode 影院编码
     * @return 当前客户端
     */
    public Optional<NettyClientWrapper> getClient(String tenantId, String cinemaCode){
        return Optional.ofNullable(nettyClientMap.get(buildClientUniqueKey(tenantId, cinemaCode)));
    }

    /**
     ** 根据通道获取客户端
     *
     * @param channel 客户端通道
     * @return 当前客户端
     */
    public Optional<NettyClientWrapper> getClient(Channel channel){
        return nettyClientMap.values().stream()
                .filter(nettyClient -> nettyClient.getChannel() == channel)
                .findFirst();
    }

    /**
     ** 移除客户端
     *
     * @param tenantId 租户ID
     * @param cinemaCode 影院编码
     */
    public void removeClient(String tenantId, String cinemaCode){
        nettyClientMap.remove(buildClientUniqueKey(tenantId, cinemaCode));
    }

    /**
     ** 移除客户端
     *
     * @param channel 客户端通道
     */
    public void removeClient(Channel channel){
        nettyClientMap.entrySet().removeIf(entry -> entry.getValue().getChannel() == channel);
    }

    /**
     ** 获取客户端数量
     *
     * @return 客户端数量
     */
    public int getSize(){
        return nettyClientMap.size();
    }

    /**
     ** 组装客户端唯一Key，格式：客户端租户ID + 下划线 + 客户端影院编码
     *
     * @param tenantId 租户ID
     * @param cinemaCode 影院编码
     * @return String 客户端唯一Key
     */
    private String buildClientUniqueKey(String tenantId, String cinemaCode){
        return StringUtils.joinWith("_",
                StringUtils.trimToEmpty(tenantId), StringUtils.trimToEmpty(cinemaCode));
    }
}
